package hu.myai.controller;

import hu.myai.model.db.AxHistory;
import hu.myai.util.DatabaseUtil;
import hu.myai.util.WebWithCookies;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.StringTokenizer;

import javax.persistence.EntityTransaction;

import org.joone.log.ILogger;
import org.joone.log.LoggerFactory;

public class SaveHistorySanford {

	private static final ILogger log = LoggerFactory.getLogger(SaveHistorySanford.class);

	WebWithCookies webWithCookies = null;

	// for database util reference
	private DatabaseUtil dbUtil = new DatabaseUtil();

	public SaveHistorySanford() {
		webWithCookies = new WebWithCookies();

		// login & save a session
		if (!webWithCookies.popCookies()) {
			if (!webWithCookies.login()) {
				log.error("Error - Falied to login");
				webWithCookies.logout();
				throw new RuntimeException("Error - Falied to login, try it again later.");
			}
			webWithCookies.pushCookies();
		}
	}

	@Override
	protected void finalize() {
		webWithCookies.logout();
	}

	protected boolean getSanfordStock(Date date) {

		log.info("Get Sanford data for: " + date);
		// the data
		SimpleDateFormat formatter;

		WebWithCookies webWithCookies = new WebWithCookies();
		if (date != null) {

			formatter = new SimpleDateFormat("dd/MM/yy");

			EntityTransaction tx = dbUtil.entityManager.getTransaction();
			tx.begin();

			try {
				String myUrl = new String("http://www.sanford.com.au/sanford/Members/Research/HistoricalData.asp?"
						+ "HistDataDate=" + formatter.format(date) + "&HistDataFormat=MetaStock&Output=Excel");

				// read date from web
				BufferedReader response = new BufferedReader(new InputStreamReader(webWithCookies
						.getURLGetString(new URL(myUrl))));

				String line = response.readLine();

				// why it is not working...
				if (line.equals("") && line.indexOf(",") == -1)
					while (line != null) {
						if (line.indexOf("<span class=\"Error\">") != -1)
							throw new Exception(line.substring(line.indexOf("<b>") + 3, line.indexOf("</b>")));
						line = response.readLine();
					}

				// Start EntityManagerFactory

				int i = 1;
				// store in db
				while (line != null && !line.equals("") && line.indexOf(",") != -1) {

					StringTokenizer tokens = new StringTokenizer(line, ",\n");
					if (tokens.countTokens() >= 5) {

						String symbol = tokens.nextToken();

						/** check whatever is in the symbol list */
						// if (Constans.forCheckSymbol.indexOf(symbol) != -1) {
						/** check if it is a ordinary stock or not */
						if (symbol.length() == 3) {
							formatter = new SimpleDateFormat("yyyyMMdd");
							date = formatter.parse(tokens.nextToken());

							// get saved record
							AxHistory history = dbUtil.getSavedHistory(date, symbol);

							if (history == null)
								history = new AxHistory();

							history.setSymbol(symbol);
							history.setDate(date);

							history.setOpen(new Double(tokens.nextToken()));
							history.setHigh(new Double(tokens.nextToken()));
							history.setLow(new Double(tokens.nextToken()));
							history.setClose(new Double(tokens.nextToken()));
							history.setVolume(new Integer(tokens.nextToken()));

							// get and set the parent of this record
							AxHistory lastRecord = dbUtil.getLastHistory(date, symbol);
							history.setParent(lastRecord);

							// get the book values just at the actual day
							if (formatter.format(date).equals(formatter.format(new Date())))
								history = getBookVolumen(history);

							dbUtil.entityManager.persist(history);
							log.debug("It is done: " + symbol);
							if (i % 40 == 0) {
								tx.commit();
								tx.begin();
								log.debug("Commit...");
							}
							i++;
						}
					}
					line = response.readLine();
				}

				response.close();

				tx.commit();
				dbUtil.entityManager.clear();

				log.info("Get Sanford data end.");

			} catch (IOException ex) {
				// Use Log4j
				log.error("IOException thrown while initializing the Sanford. Message is : " + ex.getMessage()); // LOG4J
				ex.printStackTrace();
				tx.rollback();
				return false;
			} catch (ParseException ex) {
				// Use Log4j
				log.error("ParseException thrown while initializing the Sanford. Message is : " + ex.getMessage()); // LOG4J
				ex.printStackTrace();
				tx.rollback();
				return false;
			} catch (Exception ex) {
				// Use Log4j
				log.error("Exception thrown while initializing the Sanford. Message is : " + ex.getMessage()); // LOG4J
				ex.printStackTrace();
				tx.rollback();
				return false;
			}
		} // End of if period is null

		return true;

	} // End method initInputStream

	private AxHistory getBookVolumen(AxHistory history) {

		if (history.getBookBuy() != null && history.getBookMaxBuy() != null && history.getBookMaxBuyVolume() != null
				&& history.getBookSell() != null && history.getBookMinSell() != null
				&& history.getBookMinSellVolume() != null)
			return history;

		String myUrl = "http://www.sanford.com.au/sanford/Members/MarketInfo/Quote.asp?Code=" + history.getSymbol()
				+ "&Type=MktDepth&NewWindow=1&MktDepthLevels=1";

		// read date from web
		BufferedReader response;
		try {
			response = new BufferedReader(new InputStreamReader(webWithCookies.getURLGetString(new URL(myUrl))));
			String line = response.readLine();

			// get book volume info
			int i = -1;
			while (line != null) {
				String value = null;

				// get snapshot values
				if (line.indexOf("<b>Quantity</b>") > -1)
					i = 10;
				if (i > -1) {
					int iov = line.indexOf("\"SmallBlack\">");
					try {
						value = line.substring(iov + 13, line.indexOf("</", iov - 1)).replaceAll(",", "").trim();
						new Double(value);
					} catch (Exception ex) {
						value = null;
					}
					i--;
				}

				// get the max buy value
				if (i == 4 && history.getBookMaxBuy() != null && history.getBookMinSell() == null) {
					if (value != null)
						history.setBookMinSell(new Double(value) / 100);
				}

				// get the min sell volume value
				if (i == 3 && history.getBookMaxBuyVolume() != null && history.getBookMinSellVolume() == null) {
					if (value != null)
						history.setBookMinSellVolume(new Integer(value));
				}

				// get the max buy volume value
				if (i == 2 && history.getBookMaxBuyVolume() == null) {
					if (value != null)
						history.setBookMaxBuyVolume(new Integer(value));
				}

				// get the max buy value
				if (i == 0 && history.getBookMaxBuy() == null) {
					if (value != null)
						history.setBookMaxBuy(new Double(value) / 100);
				}

				// get sum values
				int iob = line.indexOf("buyers for");
				int ios = line.indexOf("sellers with");

				// get book by value
				if (iob > -1) {
					String bookBuy = line.substring(iob + 11, line.indexOf("shares", iob - 1)).replaceAll(",", "")
							.trim();
					history.setBookBuy(new Integer(bookBuy));
				}
				// get book sell value
				if (ios > -1) {
					String bookSell = line.substring(ios + 13, line.indexOf("shares", ios - 1)).replaceAll(",", "")
							.trim();
					history.setBookSell(new Integer(bookSell));
					break;
				}
				line = response.readLine();
			}

			response.close();

		} catch (IOException e) {
			e.printStackTrace();
		}

		return history;
	}

	protected boolean getSanfordSymbol(String symbol) {
		log.info("Get Sanford symbol for: " + symbol);

		String myUrl = "", line = "";
		// the data
		SimpleDateFormat formatter;
		formatter = new SimpleDateFormat("dd/MM/yy");

		Date date = new Date(0);

		WebWithCookies webWithCookies = new WebWithCookies();

		EntityTransaction tx = dbUtil.entityManager.getTransaction();
		tx.begin();

		try {
			myUrl = new String("http://www.sanford.com.au/sanford/Members/Research/HistoricalData.asp?ASXCode="
					+ symbol + "&" + "StartDate=" + formatter.format(date) + "&HistDataFormat=MetaStock&Output=Excel");

			// read date from web
			BufferedReader response = new BufferedReader(new InputStreamReader(webWithCookies.getURLGetString(new URL(
					myUrl))));

			line = response.readLine();

			// store in db
			while (line != null && !line.equals("") && line.indexOf(",") != -1) {

				StringTokenizer tokens = new StringTokenizer(line, ",\n");
				if (tokens.countTokens() >= 5) {

					// get symbol
					tokens.nextToken();

					formatter = new SimpleDateFormat("yyyyMMdd");
					date = formatter.parse(tokens.nextToken());

					// get saved record
					AxHistory history = dbUtil.getSavedHistory(date, symbol);

					if (history == null)
						history = new AxHistory();

					history.setSymbol(symbol);
					history.setDate(date);

					Double open = new Double(tokens.nextToken());
					Double high = new Double(tokens.nextToken());
					Double low = new Double(tokens.nextToken());
					Double close = new Double(tokens.nextToken());
					Integer volume = new Integer(tokens.nextToken());

					if (open == 0.0 && close == 0.0 && high == 0.0 && low == 0.0) {
						log.error("Error - not valid record from Yahoo: " + symbol + ", " + date);
						continue;
					}

					// consolidate the result
					if (open == 0.0)
						open = close != 0.0 ? close : (high != 0.0 ? high : low);
					if (high == 0.0)
						high = close != 0.0 ? close : (open != 0.0 ? open : low);
					if (low == 0.0)
						low = close != 0.0 ? close : (high != 0.0 ? high : open);
					if (close == 0.0)
						close = low != 0.0 ? low : (high != 0.0 ? high : open);

					history.setOpen(open);
					history.setHigh(high);
					history.setLow(low);
					history.setClose(close);
					history.setVolume(volume);

					// get and set the parent of this record
					AxHistory lastRecord = dbUtil.getLastHistory(date, symbol);
					history.setParent(lastRecord);

					// get the book values just at the actual day
					if (formatter.format(date).equals(formatter.format(new Date())))
						history = getBookVolumen(history);

					dbUtil.entityManager.persist(history);
					log.debug("It is done: " + symbol);

				}
				line = response.readLine();
			}

			response.close();

			tx.commit();
			dbUtil.entityManager.clear();

			log.info("Get Sanford data end.");

		} catch (IOException ex) {
			// Use Log4j
			log.error("IOException thrown while initializing the Sanford. Message is : " + ex.getMessage()); // LOG4J
			ex.printStackTrace();
			tx.rollback();
		} catch (ParseException ex) {
			// Use Log4j
			log.error("ParseException thrown while initializing the Sanford. Message is : " + ex.getMessage()); // LOG4J
			ex.printStackTrace();
			tx.rollback();
		} catch (Exception ex) {
			// Use Log4j
			log.error("Exception thrown while initializing the Sanford. Message is : " + ex.getMessage()); // LOG4J
			log.error("URL is : " + myUrl);
			log.error("Line is : " + line);
			ex.printStackTrace();
			tx.rollback();
		}

		return true;

	}
}
